// 任务1：创建一个简单的问候函数
// 要求：
// 编写一个函数greet，接受一个名字作为参数，并返回一个问候语，例如：“Hello, [名字]! Welcome to JavaScript.”。
console.log("-----任务1-----")
function greet(name) {
    console.log(`Hello, ${name}! Welcome to JavaScript.`)
}
const name = "miku"
greet(name)

// 任务2：计算数组的平均值
// 要求：
// 编写一个函数calculateAverage，接受一个数字数组作为参数，并返回数组的平均值。
console.log("-----任务2-----")
let numbers = [1,2,3,4,5,6]
function calculateAverage(numbers) {
    let sum = 0
    numbers.forEach(number => {
        sum += number
    })
    return sum / numbers.length
}
console.log(calculateAverage(numbers))

// 任务3：检查字符串是否为回文
// 要求：
// 编写一个函数isPalindrome，接受一个字符串作为参数，判断该字符串是否为回文（正读和反读相同）。
console.log("-----任务3-----")
function isPalindrome(str) {
    const cleanStr = str.replace(/\W+/g, '').toLowerCase()
    const reversedStr = cleanStr.split('').reverse().join('')
    return reversedStr === cleanStr
}
console.log(isPalindrome("A man, a plan, a canal, Panama"))
console.log(isPalindrome("race car"))

// 任务4：实现一个简单的计数器
// 要求：
// 使用闭包实现一个简单的计数器，每次调用时返回当前的计数值。
console.log("-----任务4-----")
function clock() {
    let timer = 0
    return function() {
        console.log(timer)
        timer++
    }
}
let aClock = clock()
aClock()
aClock()
aClock()

// 任务5：过滤数组中的偶数
// 要求：
// 编写一个函数filterEvenNumbers，接受一个数字数组作为参数，返回一个只包含偶数的新数组。
console.log("-----任务5-----")
function filterEvenNumbers(numbers) {
    // filter用于创建一个新数组，其中包含所有通过特定条件的元素。
    let newNumbers = numbers.filter((number) => number % 2 === 0)
    return newNumbers
}
console.log(filterEvenNumbers(numbers))

// 任务6：实现一个简单的对象工厂
// 要求：
// 编写一个函数createPerson，接受name和age作为参数，返回一个包含这些属性的对象。
console.log("-----任务6-----")
function createPerson(name, age) {
    let person = {
        name: name,
        age: age
    }
    return person
}
console.log(createPerson("miku",17))

// 任务7：递归计算阶乘
// 要求：
// 编写一个递归函数factorial，计算一个非负整数的阶乘。
console.log("-----任务7-----")
function factorial(n) {
    if (n === 0 || n === 1) {
        return 1
    } else {
        return n * factorial(n - 1)
    }
}
console.log(factorial(5))

// 任务8：实现一个简单的事件监听器
// 要求：
// 编写一个函数addEventListener，模拟HTML元素的事件监听器功能。接受一个事件类型和一个回调函数作为参数，并在触发时调用回调函数。
console.log("-----任务8-----")
class EventTarget {
    constructor() {
        this._listeners = {} // 保存事件类型和对应回调函数的映射
    }

    // 添加事件监听器
    addEventListener(eventType, callback) {
        // 如果该事件类型不存在，则初始化
        if (!this._listeners[eventType]) {
            this._listeners[eventType] = []
        }
        // 将回调函数添加到事件类型的列表中
        this._listeners[eventType].push(callback)
    }

    // 触发事件
    dispatchEvent(eventType) {
        // 获取对应事件类型的回调函数列表
        const callbacks = this._listeners[eventType]
        if (callbacks) {
            // 遍历并调用所有回调函数
            callbacks.forEach(callback => {
                callback()
            })
        }
    }
}
const eventTarget = new EventTarget()
eventTarget.addEventListener('click', function() {
    console.log('点击事件触发了！')
});
eventTarget.dispatchEvent('click')

// 任务9：实现一个简单的Promise
// 要求：
// 使用Promise实现一个异步函数fetchData，模拟从服务器获取数据。如果成功，返回一个字符串；如果失败，抛出一个错误。
console.log("-----任务9-----")
function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            // Math.random()返回一个在 0（包含）和 1（不包含）之间的浮点数
            const success = Math.random() < 0.5
            if (success) {
                resolve("数据获取成功！")
            } else {
                reject(new Error("数据获取失败！"))
            }
        }, 1000);
    });
}
fetchData()
    .then(data => console.log(data))
    .catch(error => console.error(error.message))

// 任务10：实现一个简单的模块
// 要求：
// 使用模块模式封装一个mathUtils模块，包含add和multiply两个函数。
console.log("-----任务10-----")
let add = require("../modules/add")
let multiply = require("../modules/multiply")
console.log(add.add(1,2))
console.log(multiply.multiply(2,2))